/***************************************
 *File name: Manip.c                   *
 *Author: Gu Zhengxiong                *
 *Version: 2013.11.26                  *
 *Description:The file implements      *
 *functions in MANIP.                  *
 ***************************************/

# include <stdlib.h>//For malloc (), free ().
# include <stdio.h>//For printf ().
# include <string.h>//For strcpy (), strcmp ().

# include "StudentInfo.h"
# include "StudentGrade.h"
# include "Student.h"
# include "Manip.h"
# include "MainFace.h"

static PSTUDENT
Construct (void)
{
	PSTUDENT ps = (PSTUDENT)SecureMalloc (sizeof (STUDENT));//SecureMalloc @ MainFace.h.
	ps->pnext = NULL;
	return ps;
}
static void
Add (PSTUDENT phead, PINFO pi_in, PGRADE pg_in)
{
	PSTUDENT ps = (PSTUDENT)SecureMalloc (sizeof (STUDENT));//2
	PSTUDENT ps_tmp = phead;
	ps->pi = pi_in;
	ps->pg = pg_in;
	ps->DisplayInfoPs = DisplayInfoPs;
	ps->DisplayGradePs = DisplayGradePs;
	ps->ModifyInfo = ModifyInfo;
	ps->ModifyGrade = ModifyGrade;
	ps->DestroyPs = DestroyPs;
	while (ps_tmp->pnext != NULL)
		ps_tmp = ps_tmp->pnext;
	ps_tmp->pnext = ps;
	ps->pnext = NULL;
}
static void
DisplayInfo (PSTUDENT phead)
{
	PSTUDENT ps_tmp = phead;
	char gender_buf[7];
	printf ("\n      STUDENTS' INFORMATION\n");
	printf ("      -------------------------------------------------------\n");
	printf ("      | %-16s | %-16s | %-7s | %3s |\n", "NAME", "NUMBER", "GENDER", "AGE");
	printf ("      -------------------------------------------------------\n");
	while (ps_tmp != NULL)
	{
		if (ps_tmp == phead)
			;
		else
		{
			if (ps_tmp->pi->gender == 1)
				strcpy (gender_buf, "MALE");
			else
				strcpy (gender_buf, "FEMALE");
			printf (ALL_INFO_FORMAT, ALL_INFO_PARA);
			printf ("      -------------------------------------------------------\n");
		}
			ps_tmp = ps_tmp->pnext;
	}
}
static void
DisplayGrade (PSTUDENT phead)
{
	PSTUDENT ps_tmp = phead;
	printf ("\n      STUDENTS' GRADE\n");
	printf ("      -----------------------------------------------------------------\n");
	printf ("      | %-16s | %-16s | %s | %s | %s |\n", "NAME", "NUMBER", "MATHS", "CLANG", "ENGLISH");
	printf ("      -----------------------------------------------------------------\n");
	while (ps_tmp != NULL)
	{
		if (ps_tmp == phead)
			;
		else
		{
			printf (ALL_GRADE_FORMAT, ALL_GRADE_PARA);
			printf ("      -----------------------------------------------------------------\n");
		}
			ps_tmp = ps_tmp->pnext;
	}
}
PSTUDENT
Inquire (PSTUDENT phead, int type, char * s)
{
	PSTUDENT ps_tmp = phead;
	while (ps_tmp != NULL)
	{
		if (ps_tmp == phead)
			;
		else
		{
			switch (type)
			{
				case SEARCH_NUM: 
								if (strcmp (s, ps_tmp->pi->number) == 0)
									return ps_tmp;
								break;
				case SEARCH_NAME:
								if (strcmp (s, ps_tmp->pi->name) == 0)
									return ps_tmp;
								break;
			}
		}
		ps_tmp = ps_tmp->pnext;
	}
	return NULL;
}
static PSTUDENT
InquireBefore (PSTUDENT phead, int type, char * s)
{
	PSTUDENT ps_tmp = phead;
	while (ps_tmp->pnext != NULL)
	{
		switch (type)
		{
			case SEARCH_NUM: 
							if (strcmp (s, ps_tmp->pnext->pi->number) == 0)
								return ps_tmp;
							break;
			case SEARCH_NAME:
							if (strcmp (s, ps_tmp->pnext->pi->name) == 0)
								return ps_tmp;
							break;
		}
	ps_tmp = ps_tmp->pnext;
	}
	return NULL;
}
static void
SaveToFile (PSTUDENT phead)
{
	FILE *pf = fopen ("Student", "w");
	PSTUDENT ps_tmp = phead;
	if (pf == NULL)
	{
		ShowError (FILE_ERR);
		return;
	}
	while (ps_tmp != NULL)
	{
		if (ps_tmp == phead)
			;
		else
		{
			fwrite (ps_tmp->pi, sizeof (INFO), 1, pf);
			fwrite (ps_tmp->pg, sizeof (GRADE), 1, pf);
		}
		ps_tmp = ps_tmp->pnext;
	}
	fclose (pf);
}
static int
LoadFromFile (PSTUDENT phead, int *c)//I didn't check.
{
	FILE *pf = fopen ("Student", "r");
	PINFO pi_tmp = (PINFO)SecureMalloc (sizeof (INFO));//3
	PGRADE pg_tmp = (PGRADE)SecureMalloc (sizeof (GRADE));//4
	if (pf == NULL)
	{
		ShowError (FILE_ERR);
		return 0;
	}
	while (fread (pi_tmp, sizeof (INFO), 1, pf) != 0 && fread (pg_tmp, sizeof (GRADE), 1, pf) != 0)
	{
		if (Inquire (phead, SEARCH_NAME, pi_tmp->name) != NULL || Inquire (phead, SEARCH_NUM, pi_tmp->number) != NULL)
		{
			ShowError (EXISTED);
			continue;
		}
		if (IsValidGrade (pg_tmp->clang) && IsValidGrade (pg_tmp->english) && IsValidGrade (pg_tmp->maths))
		{
			PINFO pi_real = (PINFO)SecureMalloc (sizeof (INFO));//5
			PGRADE pg_real = (PGRADE)SecureMalloc (sizeof (GRADE));//6
			*(pi_real) = *(pi_tmp);
			*(pg_real) = *(pg_tmp);
			Add (phead, pi_real, pg_real);
			(*c)++;
		}
		else
		{
			ShowError (IN_ERR);
			continue;
		}
	}
	free (pi_tmp);
	free (pg_tmp);
	fclose (pf);
	return 1;
}
static void
Destroy (PSTUDENT phead)
{
	PSTUDENT ps_tmp = phead;
	while (ps_tmp != NULL)
	{
		if (ps_tmp == phead)
			;
		else
		{	free (ps_tmp->pg);
			free (ps_tmp->pi);
		}
		ps_tmp = ps_tmp->pnext;
	}
}
PMANIP
ManipInitialize (void)
{
	PMANIP pm = (PMANIP)SecureMalloc (sizeof (MANIP));//7
	pm->Construct = Construct;
	pm->Add = Add;
	pm->Inquire = Inquire;
	pm->InquireBefore = InquireBefore;
	pm->DisplayInfo = DisplayInfo;
	pm->DisplayGrade = DisplayGrade;
	pm->SaveToFile = SaveToFile;
	pm->LoadFromFile = LoadFromFile;
	pm->Destroy = Destroy;

	return pm;
}